package com.jza04.flightbooking.controller;

import com.jza04.flightbooking.entity.Flight;
import com.jza04.flightbooking.service.FlightService;
import com.jza04.flightbooking.service.PassengerService;
import com.jza04.flightbooking.service.TicketService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 统计面板控制器
 * 提供航班收入统计、数据可视化展示和报表导出功能
 */
@Controller
@RequestMapping("/statistics")
public class StatisticsController {

    @Autowired
    private TicketService ticketService;
    
    @Autowired
    private FlightService flightService;
    
    @Autowired
    private PassengerService passengerService;
    
    /**
     * 显示统计面板页面
     * @param model 用于向视图传递数据的模型对象
     * @return 统计面板视图路径
     * @apiNote 聚合展示总收入、航班收入分布、旅客总数等核心指标
     */
    @GetMapping
    public String showStatisticsPanel(Model model) {
        // 获取总收入
        BigDecimal totalRevenue = ticketService.getTotalRevenue();
        model.addAttribute("totalRevenue", totalRevenue != null ? totalRevenue : BigDecimal.ZERO);
        
        try {
            // 获取按航班统计的收入
            Map<String, BigDecimal> revenueByFlight = ticketService.getRevenueByFlight();
            // 确保revenueByFlight不为null
            if (revenueByFlight == null) {
                revenueByFlight = new HashMap<>();
            }
            model.addAttribute("revenueByFlight", revenueByFlight);
        } catch (Exception e) {
            // 如果出现异常，则使用空的Map
            model.addAttribute("revenueByFlight", new HashMap<String, BigDecimal>());
        }
        
        // 获取所有航班信息
        model.addAttribute("flights", flightService.findAllFlights());
        
        // 获取旅客总数
        model.addAttribute("passengerCount", passengerService.findAllPassengers().size());
        
        return "statistics/dashboard";
    }
    
    /**
     * 获取总收入数据（API接口）
     * @return 包含总收入的JSON对象，格式：{"totalRevenue": 金额}
     */
    @GetMapping("/total-revenue")
    @ResponseBody
    public Map<String, Object> getTotalRevenue() {
        Map<String, Object> result = new HashMap<>();
        result.put("totalRevenue", ticketService.getTotalRevenue());
        return result;
    }
    
    /**
     * 获取指定日期范围的收入数据（API接口）
     * @param startLocalDate 起始日期（格式：yyyy-MM-dd）
     * @param endLocalDate 结束日期（格式：yyyy-MM-dd）
     * @return 包含日期范围收入的JSON对象，格式：{
     *     "revenue": 金额,
     *     "startDate": "起始日期",
     *     "endDate": "结束日期"
     * }
     * @throws Exception 当日期格式错误或查询失败时抛出异常
     */
    @GetMapping("/revenue-by-date")
    @ResponseBody
    public Map<String, Object> getRevenueByDate(
            @RequestParam("startDate") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startLocalDate,
            @RequestParam("endDate") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endLocalDate) {
        try {
            Map<String, Object> result = new HashMap<>();
            
            // 转换为Date对象
            Date startDate = Date.from(startLocalDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
            Date endDate = Date.from(endLocalDate.plusDays(1).atStartOfDay(ZoneId.systemDefault()).minusSeconds(1).toInstant());
            
            BigDecimal revenue = ticketService.getRevenueByDateRange(startDate, endDate);
            result.put("revenue", revenue != null ? revenue : BigDecimal.ZERO);
            result.put("startDate", startLocalDate.toString());
            result.put("endDate", endLocalDate.toString());
            return result;
        } catch (Exception e) {
            Map<String, Object> result = new HashMap<>();
            result.put("revenue", 0);
            result.put("error", "日期格式错误或查询失败：" + e.getMessage());
            return result;
        }
    }
    
    /**
     * 获取按航班统计的收入数据（API接口）
     * @return 航班收入映射表，格式：{ "航班号": 收入金额, ... }
     */
    @GetMapping("/revenue-by-flight")
    @ResponseBody
    public Map<String, BigDecimal> getRevenueByFlight() {
        try {
            Map<String, BigDecimal> result = ticketService.getRevenueByFlight();
            return result != null ? result : new HashMap<>();
        } catch (Exception e) {
            return new HashMap<>();
        }
    }
    
    /**
     * 导出统计报表
     * @param response HTTP响应对象
     * @param format 导出格式（当前支持csv格式）
     * @throws IOException 当输出流操作失败时抛出
     * @apiNote 支持CSV格式导出，包含总收入、旅客总数和航班明细数据
     */
    @GetMapping("/export-report")
    public void exportReport(HttpServletResponse response,
                            @RequestParam(value = "format", defaultValue = "csv") String format) throws IOException {
        if ("csv".equalsIgnoreCase(format)) {
            exportCsvReport(response);
        } else {
            // 默认导出CSV格式
            exportCsvReport(response);
        }
    }
    
    /**
     * 生成CSV格式报表（内部方法）
     * @param response HTTP响应对象
     * @throws IOException 当输出流操作失败时抛出
     * @implNote 生成的CSV包含：
     * 1. 报表标题和生成日期
     * 2. 总收入
     * 3. 旅客总数
     * 4. 航班明细（航班号、起降城市、起飞时间、票价、售票数和收入）
     */
    private void exportCsvReport(HttpServletResponse response) throws IOException {
        // 设置响应头，告诉浏览器这是一个CSV文件下载
        response.setContentType("text/csv");
        response.setCharacterEncoding("UTF-8");
        
        // 设置文件名
        String fileName = "航班收入报表_" + LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")) + ".csv";
        response.setHeader("Content-Disposition", "attachment; filename=" + 
                new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
        
        // 获取收入数据
        BigDecimal totalRevenue = ticketService.getTotalRevenue();
        Map<String, BigDecimal> revenueByFlight = ticketService.getRevenueByFlight();
        List<Flight> flights = flightService.findAllFlights();
        
        // 写入CSV内容
        StringBuilder csvContent = new StringBuilder();
        
        // 添加标题行
        csvContent.append("航班报表信息\n");
        csvContent.append("生成日期：,").append(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))).append("\n\n");
        
        // 添加总收入
        csvContent.append("总收入：,￥").append(totalRevenue).append("\n\n");
        
        // 添加旅客总数
        csvContent.append("旅客总数：,").append(passengerService.findAllPassengers().size()).append("\n\n");
        
        // 添加航班收入明细
        csvContent.append("航班号,始发地,目的地,起飞时间,票价,已售票数,收入\n");
        
        // 获取所有航班信息并按航班ID分组显示收入
        for (Flight flight : flights) {
            BigDecimal revenue = revenueByFlight.getOrDefault(flight.getFlightId(), BigDecimal.ZERO);
            int soldTickets = ticketService.findTicketsByFlightId(flight.getFlightId()).size();
            
            csvContent.append(flight.getFlightId()).append(",")
                     .append(flight.getDepartureCity()).append(",")
                     .append(flight.getArrivalCity()).append(",")
                     .append(flight.getDepartureTime()).append(",")
                     .append("￥").append(flight.getBasePrice()).append(",")
                     .append(soldTickets).append(",")
                     .append("￥").append(revenue).append("\n");
        }
        
        // 获取输出流
        OutputStream outputStream = response.getOutputStream();
        
        // 添加BOM标记，确保Excel正确显示中文
        byte[] bomBytes = {(byte)0xEF, (byte)0xBB, (byte)0xBF};
        outputStream.write(bomBytes);
        
        // 将CSV内容转换为字节并写入输出流
        outputStream.write(csvContent.toString().getBytes(StandardCharsets.UTF_8));
        outputStream.flush();
    }
}